package com.ff.dao;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;

import org.springframework.stereotype.Repository;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSErrorCode;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.ServiceException;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.ObjectMetadata;

@Repository
public class OssDaoImpl implements OssDao {

	// 创建Bucket.
	@Override
	public void ensureBucket(OSSClient client, String bucketName) throws OSSException, ClientException {
		try {
			// 创建bucket
			client.createBucket(bucketName);
		} catch (ServiceException e) {
			if (!OSSErrorCode.BUCKET_ALREADY_EXISTS.equals(e.getErrorCode())) {
				// 如果Bucket已经存在，则忽略
				throw e;
			}
		}
	}

	@Override
	public OSSObject findObject(OSSClient client, String bucketName, String key) throws OSSException, ClientException {
		OSSObject object = null;
		try {
			object = client.getObject(bucketName, key);
		} catch (ServiceException e) {
			if (!OSSErrorCode.NO_SUCH_KEY.equals(e.getErrorCode())) {
				// 非key未找到异常，需要被调用者处理
				throw e;
			}
		}
		return object;
	}

	@Override
	public void createFolder(OSSClient client, String bucketName, String folderName) throws IOException {
		// 要创建的文件夹名称,在满足Object命名规则的情况下以"/"结尾
		if (!folderName.endsWith("/")) {
			folderName += "/";
		}
		ObjectMetadata objectMeta = new ObjectMetadata();
		/*
		 * 这里的size为0,注意OSS本身没有文件夹的概念,这里创建的文件夹本质上是一个size为0的Object,
		 * dataStream仍然可以有数据
		 * 照样可以上传下载,只是控制台会对以"/"结尾的Object以文件夹的方式展示,用户可以利用这种方式来实现
		 * 文件夹模拟功能,创建形式上的文件夹
		 */
		byte[] buffer = new byte[0];
		ByteArrayInputStream in = new ByteArrayInputStream(buffer);
		objectMeta.setContentLength(0);
		try {
			client.putObject(bucketName, folderName, in, objectMeta);
		} finally {
			in.close();
		}
	}

	// 把Bucket设置为所有人可读
	// private static void setBucketPublicReadable(OSSClient client, String
	// bucketName) throws OSSException, ClientException {
	// //创建bucket
	// client.createBucket(bucketName);
	//
	// //设置bucket的访问权限，public-read-write权限
	// client.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
	// }

	// 上传文件
	@Override
	public void uploadFile(OSSClient client, String bucketName, String key, String contentType, long contentLength,
			InputStream input) throws OSSException, ClientException {
		ObjectMetadata objectMeta = new ObjectMetadata();
		objectMeta.setContentLength(contentLength);
		// 可以在metadata中标记文件类型
		objectMeta.setContentType(contentType);// "image/jpeg"

		client.putObject(bucketName, key, input, objectMeta);
	}

	@Override
	public String getObjectUri(OSSClient client, String bucketName, String key) throws ClientException {
		Date date = new Date();
		date.setTime(date.getTime() + (7 * 24 * 3600 * 1000)); // url链接保留一周
		URL url = client.generatePresignedUrl(bucketName, key, date);
		String uri = null;
		if (url != null) {
			uri = url.toString();
			uri = uri.substring(0, uri.indexOf('?', 0));
		}
		return uri;
	}

	@Override
	public boolean deleteObject(OSSClient client, String bucketName, String key) throws OSSException, ClientException {
		if (findObject(client, bucketName, key) != null) {
			client.deleteObject(bucketName, key);
			return true;
		} else {
			return false;
		}
	}

	@Override
	public ObjectListing listObject(OSSClient client, String bucketName, String folderName)
			throws OSSException, ClientException {
		// 构造ListObjectsRequest请求
		ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
		// "/" 为文件夹的分隔符
		listObjectsRequest.setDelimiter("/");
		if ((folderName != null) && (!folderName.isEmpty())) {
			// 列出fun目录下的所有文件和文件夹
			listObjectsRequest.setPrefix(folderName + "/");
		}
		return client.listObjects(listObjectsRequest);
	}

	/**
	 * @Title: getPrivatePicUri
	 * @Description: TODO
	 * @param client
	 * @param bucket
	 * @param key
	 * @return
	 * @see com.ff.dao.OssDao#getPrivatePicUri(com.aliyun.oss.OSSClient, java.lang.String, java.lang.String, java.lang.Integer)
	 */
	@Override
	public String getPrivatePicUri(OSSClient client, String bucket, String key, Integer expiration) {
		GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, key);
		Date date = new Date();
		date.setTime(date.getTime() + expiration); 
		request.setExpiration(date);
		URL url = client.generatePresignedUrl(request);
		return url.toString();
	}
}
